package com.miracle.toolbox.keyword;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 敏感词过滤
 */
public class KeywordUtil {
	private static final Logger log = LoggerFactory.getLogger(KeywordUtil.class);

	public static final String KEYWORD_PATH = "E:\\ideaworkspace\\csi-loc\\cs-parent\\cs-parent\\cs-busi-parent\\cs-busi-service\\src\\main\\java\\com\\huateng" +
			"\\cs\\busi\\service\\outwardCheck\\outwardCheckKeyword\\k.txt";

	private KeywordHandler keywordHandler;
	private Map keywordMap;

	/**
	 * 最小匹配规则：匹配到最短的关键字立即退出该轮匹配
	 * eg：床前明月光（关键字：床前、床前明月），匹配到"床前"立即结束，无法继续匹配"床前明月"
	 */
	public static int minMatchTYpe = 1;

	/**
	 * 最大匹配规则：匹配到最短的关键字后继续匹配更长的关键字
	 * eg：床前明月光（关键字：床前、床前明月），匹配到"床前"不结束，继续匹配"床前明月"
	 */
	public static int maxMatchType = 2;

	/**
	 * 构造函数，初始化敏感词库
	 */
	public KeywordUtil(KeywordHandler keywordHandler) {
		this.keywordHandler = keywordHandler;
		this.keywordMap = keywordHandler.getkeywordMap();
	}

	/**
	 * 判断文字是否包含敏感字符
	 * @param txt  文字
	 * @param matchType  匹配规则 1：最小匹配规则，2：最大匹配规则
	 * @return 若包含返回true，否则返回false
	 */
	public boolean isContaintKeyword(String txt,int matchType){
		boolean flag = false;
		for(int i = 0 ; i < txt.length() ; i++){
			int matchFlag = checkKeyword(txt, i, matchType); //判断是否包含敏感字符
			if(matchFlag > 0){ //大于0存在，返回true
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 获取文字中的敏感词
	 * @param txt 文字
	 * @param matchType 匹配规则 1：最小匹配规则，2：最大匹配规则
	 * @return
	 */
	public Set<String> getKeyWord(String txt , int matchType){
		Set<String> keywordList = new HashSet<>();

		for(int i = 0 ; i < txt.length() ; i++){
			int length = checkKeyword(txt, i, matchType);  //判断是否包含敏感字符
			if(length > 0){ //存在,加入list中
				keywordList.add(txt.substring(i, i+length));
				i = i + length - 1; //减1的原因，是因为for会自增
			}
		}

		return keywordList;
	}

	/**
	 * 替换敏感字字符
	 * @param txt
	 * @param matchType
	 * @param replaceChar 替换字符，默认*
	 */
	public String replaceKeyword(String txt,int matchType,String replaceChar){

		String resultTxt = txt;
		String replaceString;
		String word;

		for(int i = 0 ; i < txt.length() ; i++){
			int length = checkKeyword(txt, i, matchType);  //判断是否包含敏感字符
			if(length > 0){ //存在,加入list中
				word = txt.substring(i, i+length);
				replaceString = getReplaceChars(replaceChar, word.length());
				resultTxt = resultTxt.replace(word, replaceString);
				i = i + length - 1; //减1的原因，是因为for会自增
			}
		}

		return resultTxt;
	}

	/**
	 * 替换敏感字字符
	 * @param txt
	 * @param replaceChar 替换字符，默认*
	 */
	public String replaceKeyword(String txt, Set<String> set ,String replaceChar){
		String resultTxt = txt;
		Iterator<String> iterator = set.iterator();
		String word = null;
		String replaceString = null;
		while (iterator.hasNext()) {
			word = iterator.next();
			replaceString = getReplaceChars(replaceChar, word.length());
			resultTxt = resultTxt.replaceAll(word, replaceString);
		}

		return resultTxt;
	}

	/**
	 * 获取替换字符串
	 * @param replaceChar
	 * @param length
	 * @return
	 */
	private String getReplaceChars(String replaceChar,int length){
		String resultReplace = replaceChar;
		for(int i = 1 ; i < length ; i++){
			resultReplace += replaceChar;
		}

		return resultReplace;
	}

	/**
	 * 检查文字中是否包含敏感字符，检查规则如下：
	 * @param txt
	 * @param beginIndex
	 * @param matchType
	 * @return，如果存在，则返回敏感词字符的长度，不存在返回0
	 */
	public int checkKeyword(String txt,int beginIndex,int matchType){
		boolean  flag = false; //敏感词结束标识位：用于敏感词只有1位的情况
		int matchFlag = 0; //匹配标识数默认为0
		char word;
		Map nowMap = keywordMap;
		for(int i = beginIndex; i < txt.length() ; i++){
			word = txt.charAt(i);
			nowMap = (Map) nowMap.get(word); //获取指定key
			if(nowMap != null){ //存在，则判断是否为最后一个
				matchFlag++; //找到相应key，匹配标识+1
				if("1".equals(nowMap.get("isEnd"))){ //如果为最后一个匹配规则,结束循环，返回匹配标识数
					flag = true; //结束标志位为true
					if(KeywordUtil.minMatchTYpe == matchType){ //最小规则，直接返回,最大规则还需继续查找
						break;
					}
				}
			} else{ //不存在，直接返回
				break;
			}
		}
		if(matchFlag < 2 || !flag){ //长度必须大于等于1，为词
			matchFlag = 0;
		}
		return matchFlag;
	}


	public static void main(String[] args) throws IOException {
		KeywordHandler keywordHandler = KeywordHandler.getInstance().initKeyWord(KeywordHandler.readSensitiveWordByFile(KeywordUtil.KEYWORD_PATH));
		KeywordUtil filter = new KeywordUtil(keywordHandler);
		log.info("敏感词的数量：" + filter.keywordMap.size());

		String string = "我在线播放你在线爆";
		log.info("待检测语句字数：" + string.length());

		long beginTime = System.currentTimeMillis();
		Set<String> set = filter.getKeyWord(string, 2);
		long endTime = System.currentTimeMillis();
		log.info("语句中包含敏感词的个数为：" + set.size() + "。包含：" + set);
		log.info("总共消耗时间为：" + (endTime - beginTime));

		String s = filter.replaceKeyword(string, 2, "*");
		log.info("替换后字符串："+s);
	}
}
